﻿
namespace Teal.Compiler {

    /// <summary>
    /// 表示一个表达式。
    /// </summary>
    public abstract partial class Expression {

        /// <summary>
        /// 将当前表达式解析为一个符号。
        /// </summary>
        /// <param name="context">用于存储所有解析信息的上下文对象。</param>
        /// <param name="symbolUsage">当前符号的使用场景。</param>
        /// <param name="instance">返回当前符号的所属实例对象。</param>
        /// <returns>返回解析后的符号对象。如果解析出现错误则返回 null。</returns>
        public virtual ISymbol resolveAsSymbol(ResolveContext context, SymbolUsage symbolUsage, out Expression instance) {
            //instance = null;
            //return resolveAsValue(context);

            throw new Unreachable();
        }

        /// <summary>
        /// 先将表达式解析为符号，然后获取其值。
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        protected Expression resolveAsSymbolAndGetValue(ResolveContext context) {
            //Expression instance;
            //var resolvedSymbol = resolveAsSymbol(context, SymbolUsage.getValue, out instance);
            //if (resolvedSymbol == null) {
            //    return null;
            //}
            //return resolvedSymbol.getValue(context, instance, this);

            throw new Unreachable();
        }

    }

    /// <summary>
    /// 表示符号的使用场景。
    /// </summary>
    public enum SymbolUsage {

        /// <summary>
        /// 用于计算值。
        /// </summary>
        getValue,

        /// <summary>
        /// 用于赋值。
        /// </summary>
        setValue,

        /// <summary>
        /// 用于计算且赋值。
        /// </summary>
        getSetValue,

        /// <summary>
        /// 用于赋值，并允许自动创建符号。
        /// </summary>
        define,

        /// <summary>
        /// 用于作为其它成员的容器。
        /// </summary>
        containerMember,

        /// <summary>
        /// 用于函数调用参数。
        /// </summary>
        argument,

    }

    ///// <summary>
    ///// 表示一个标识符。
    ///// </summary>
    //public partial class Identifier {

    //    /// <summary>
    //    /// 将当前表达式解析为一个符号。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <param name="symbolUsage">当前符号的使用场景。</param>
    //    /// <param name="instance">返回当前符号的所属实例对象。</param>
    //    /// <returns>返回解析后的符号对象。如果解析出现错误则返回 null。</returns>
    //    public override ISymbol resolveAsSymbol(ResolveContext context, SymbolUsage symbolUsage, out Expression instance) {

    //        // 解析为局部变量。
    //        if (context.currentFlowControl != null) {
    //            var variable = context.currentFlowControl.findVariable(value);
    //            if (variable != null) {
    //                instance = null;
    //                return variable;
    //            }
    //        }

    //        // 解析为成员引用。
    //        var members = context.currentMemberDefinition.bindAllMembers(value, 0);
    //        if (members != null) {

    //            // 目前无法确定成员是静态还是非静态的，使用 Expression.empty 标记可能为 this 或非 this。
    //            instance = Expression.empty;
    //            return ResolveHelper.checkOverload(members, value, this);
    //        }

    //        // 自动创建变量。
    //        if (symbolUsage == SymbolUsage.define) {
    //            var variable = new Variable() {
    //                name = this,
    //                declareState = State.on,
    //                resolvedType = PredefinedTypes.var
    //            };
    //            context.currentFlowControl.addVariable(variable);
    //            instance = null;
    //            return variable;
    //        }

    //        ResolveHelper.reportBindSymbolError(context.currentMemberDefinition, null, value, 0, this);
    //        instance = null;
    //        return null;

    //    }

    //    /// <summary>
    //    /// 将当前表达式作为值解析。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <returns>返回解析后的新表达式，它的所有子表达式都已经被解析。如果解析出现错误则返回 null。</returns>
    //    public override Expression resolveAsValue(ResolveContext context) {
    //        return base.resolveAsSymbolAndGetValue(context);
    //    }

    //}

    ///// <summary>
    ///// 表示一个魔法变量。
    ///// </summary>
    //public partial class MagicVariable {

    //    /// <summary>
    //    /// 将当前表达式解析为一个符号。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <param name="symbolUsage">当前符号的使用场景。</param>
    //    /// <param name="instance">返回当前符号的所属实例对象。</param>
    //    /// <returns>返回解析后的符号对象。如果解析出现错误则返回 null。</returns>
    //    public override ISymbol resolveAsSymbol(ResolveContext context, SymbolUsage symbolUsage, out Expression instance) {
    //        instance = null;
    //        switch (value) {
    //            case "global":
    //            case "callee":
    //            case "self":
    //                return resolveAsMember(context.currentMemberDefinition, MemberUsage.type);
    //            default:
    //                Compiler.error(ErrorCode.none, "无效的魔法变量", this);
    //                return null;
    //        }
    //    }

    //}

    ///// <summary>
    ///// 表示 null 常量。
    ///// </summary>
    //public partial class NullLiteral {

    //    /// <summary>
    //    /// 将当前表达式解析为一个符号。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <param name="symbolUsage">当前符号的使用场景。</param>
    //    /// <param name="instance">返回当前符号的所属实例对象。</param>
    //    /// <returns>返回解析后的符号对象。如果解析出现错误则返回 null。</returns>
    //    public override ISymbol resolveAsSymbol(ResolveContext context, SymbolUsage symbolUsage, out Expression instance) {
    //        if (symbolUsage == SymbolUsage.containerMember) {
    //            Compiler.error(ErrorCode.none, "无法获取 null 的成员", this);
    //            instance = null;
    //            return null;
    //        }
    //        return base.resolveAsSymbol(context, symbolUsage, out instance);
    //    }

    //}

    ///// <summary>
    ///// 表示 this 常量。
    ///// </summary>
    //public partial class ThisLiteral {

    //    /// <summary>
    //    /// 获取当前 this 的目标类型。
    //    /// </summary>
    //    public TypeReference targetType;

    //    /// <summary>
    //    /// 获取当前表达式解析后的返回值类型。
    //    /// </summary>
    //    public override TypeReference resolvedType {
    //        get {
    //            return targetType;
    //        }
    //    }

    //    /// <summary>
    //    /// 将当前表达式解析为一个符号。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <param name="symbolUsage">当前符号的使用场景。</param>
    //    /// <param name="instance">返回当前符号的所属实例对象。</param>
    //    /// <returns>返回解析后的符号对象。如果解析出现错误则返回 null。</returns>
    //    public override ISymbol resolveAsSymbol(ResolveContext context, SymbolUsage symbolUsage, out Expression instance) {
    //        instance = null;
    //        var member = context.currentMemberDefinition.memberReference;
    //        if (member.modifiers.hasFlag(Modifiers.@static | Modifiers.@const)) {
    //            Compiler.error(ErrorCode.none, "当前上下文不允许使用“this”", this);
    //            return null;
    //        }

    //        targetType = member.parentType;
    //        return this;
    //    }

    //    /// <summary>
    //    /// 将当前表达式作为右值解析。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <returns>返回解析后的新表达式，它的所有子表达式都已经被解析。如果解析出现错误则返回 null。</returns>
    //    public override Expression resolveAsValue(ResolveContext context) {
    //        return base.resolveAsSymbolAndGetValue(context); ;
    //    }

    //}

    ///// <summary>
    ///// 表示 base 常量。
    ///// </summary>
    //public partial class BaseLiteral {

    //    /// <summary>
    //    /// 获取当前 base 的目标类型。
    //    /// </summary>
    //    public TypeReference targetType;

    //    /// <summary>
    //    /// 获取当前表达式解析后的返回值类型。
    //    /// </summary>
    //    public override TypeReference resolvedType {
    //        get {
    //            return targetType;
    //        }
    //    }

    //    /// <summary>
    //    /// 将当前表达式解析为一个符号。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <param name="symbolUsage">当前符号的使用场景。</param>
    //    /// <param name="instance">返回当前符号的所属实例对象。</param>
    //    /// <returns>返回解析后的符号对象。如果解析出现错误则返回 null。</returns>
    //    public override ISymbol resolveAsSymbol(ResolveContext context, SymbolUsage symbolUsage, out Expression instance) {
    //        var member = context.currentMemberDefinition.memberReference;
    //        instance = null;
    //        if (member.modifiers.hasFlag(Modifiers.@static)) {
    //            Compiler.error(ErrorCode.none, "当前上下文不允许使用“base”", this);
    //            return null;
    //        }

    //        // object 类无基类。
    //        if (targetType.baseType == null) {
    //            Compiler.error(ErrorCode.none, "当前上下文不允许使用“base”（当前类不存在基类）", this);
    //            return null;
    //        }

    //        targetType = member.parentType;
    //        return this;
    //    }

    //    /// <summary>
    //    /// 将当前表达式作为右值解析。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <returns>返回解析后的新表达式，它的所有子表达式都已经被解析。如果解析出现错误则返回 null。</returns>
    //    public override Expression resolveAsValue(ResolveContext context) {
    //        return base.resolveAsSymbolAndGetValue(context); ;
    //    }

    //}
    
    ///// <summary>
    ///// 表示内置类型字面量。
    ///// </summary>
    //public partial class PredefinedTypeLiteral {

    //    /// <summary>
    //    /// 将当前表达式解析为一个符号。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <param name="symbolUsage">当前符号的使用场景。</param>
    //    /// <param name="instance">返回当前符号的所属实例对象。</param>
    //    /// <returns>返回解析后的符号对象。如果解析出现错误则返回 null。</returns>
    //    public override ISymbol resolveAsSymbol(ResolveContext context, SymbolUsage symbolUsage, out Expression instance) {
    //        instance = null;
    //        return resolveAsMember(context.currentMemberDefinition, MemberUsage.type);
    //    }

    //    /// <summary>
    //    /// 将当前表达式作为值解析。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <returns>返回解析后的新表达式，它的所有子表达式都已经被解析。如果解析出现错误则返回 null。</returns>
    //    public override Expression resolveAsValue(ResolveContext context) {
    //        return base.resolveAsSymbolAndGetValue(context);
    //    }

    //}

    ///// <summary>
    ///// 表示一个泛型表达式。
    ///// </summary>
    //public partial class GenericTypeExpression {

    //    /// <summary>
    //    /// 将当前表达式解析为一个符号。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <param name="symbolUsage">当前符号的使用场景。</param>
    //    /// <param name="instance">返回当前符号的所属实例对象。</param>
    //    /// <returns>返回解析后的符号对象。如果解析出现错误则返回 null。</returns>
    //    public override ISymbol resolveAsSymbol(ResolveContext context, SymbolUsage symbolUsage, out Expression instance) {

    //        // 暂时无法确定是否是静态的。
    //        instance = Expression.empty;

    //        // 解析泛型定义。
    //        var genericDefinition = context.currentMemberDefinition.bindAllMembers(elementType.value, genericArguments.Count);
    //        if (genericDefinition == null) {
    //            ResolveHelper.reportBindSymbolError(context.currentMemberDefinition, null, elementType.value, genericArguments.Count, this);
    //            return null;
    //        }

    //        // 确保源定义可重载。
    //        genericDefinition = ResolveHelper.checkOverload(genericDefinition, elementType.value, this);
    //        if (genericDefinition == null) {
    //            return null;
    //        }

    //        return ResolveHelper.makeGenericSymbol(genericDefinition, genericArguments, context, symbolUsage, this);

    //    }

    //    /// <summary>
    //    /// 将当前表达式作为值解析。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <returns>返回解析后的新表达式，它的所有子表达式都已经被解析。如果解析出现错误则返回 null。</returns>
    //    public override Expression resolveAsValue(ResolveContext context) {
    //        return base.resolveAsSymbolAndGetValue(context); ;
    //    }

    //}

    ///// <summary>
    ///// 表示一个数组类型表达式。
    ///// </summary>
    //public partial class ArrayTypeExpression {

    //    /// <summary>
    //    /// 将当前表达式解析为一个符号。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <param name="symbolUsage">当前符号的使用场景。</param>
    //    /// <param name="instance">返回当前符号的所属实例对象。</param>
    //    /// <returns>返回解析后的符号对象。如果解析出现错误则返回 null。</returns>
    //    public override ISymbol resolveAsSymbol(ResolveContext context, SymbolUsage symbolUsage, out Expression instance) {
    //        instance = null;
    //        return resolveAsMember(context.currentMemberDefinition, MemberUsage.type);
    //    }

    //    /// <summary>
    //    /// 将当前表达式作为值解析。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <returns>返回解析后的新表达式，它的所有子表达式都已经被解析。如果解析出现错误则返回 null。</returns>
    //    public override Expression resolveAsValue(ResolveContext context) {
    //        return base.resolveAsSymbolAndGetValue(context);
    //    }

    //}

    ///// <summary>
    ///// 表示一个指针表达式。
    ///// </summary>
    //public partial class PtrTypeExpression {

    //    /// <summary>
    //    /// 将当前表达式解析为一个符号。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <param name="symbolUsage">当前符号的使用场景。</param>
    //    /// <param name="instance">返回当前符号的所属实例对象。</param>
    //    /// <returns>返回解析后的符号对象。如果解析出现错误则返回 null。</returns>
    //    public override ISymbol resolveAsSymbol(ResolveContext context, SymbolUsage symbolUsage, out Expression instance) {
    //        instance = null;
    //        return resolveAsMember(context.currentMemberDefinition, MemberUsage.type);
    //    }

    //    /// <summary>
    //    /// 将当前表达式作为值解析。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <returns>返回解析后的新表达式，它的所有子表达式都已经被解析。如果解析出现错误则返回 null。</returns>
    //    public override Expression resolveAsValue(ResolveContext context) {
    //        return base.resolveAsSymbolAndGetValue(context);
    //    }

    //}

    ///// <summary>
    ///// 表示一个成员调用表达式。
    ///// </summary>
    //public partial class MemberCallExpression {

    //    /// <summary>
    //    /// 将当前表达式解析为一个符号。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <param name="symbolUsage">当前符号的使用场景。</param>
    //    /// <param name="instance">返回当前符号的所属实例对象。</param>
    //    /// <returns>返回解析后的符号对象。如果解析出现错误则返回 null。</returns>
    //    public override ISymbol resolveAsSymbol(ResolveContext context, SymbolUsage symbolUsage, out Expression instance) {

    //        Expression targetInstance;
    //        var resolvedTarget = target.resolveAsSymbol(context, SymbolUsage.containerMember, out targetInstance);
    //        if (resolvedTarget == null) {
    //            instance = null;
    //            return null;
    //        }

    //        bool fliterProtectedMembers = false;

    //        // Namespace.prop
    //        var resolvedTargetContainer = resolvedTarget as MemberContainerReference;
    //        if (resolvedTargetContainer != null) {
    //            instance = null;
    //            goto resolveArgument;
    //        }

    //        // base.prop
    //        var baseSymbol = resolvedTarget as BaseLiteral;
    //        if (baseSymbol != null) {
    //            instance = baseSymbol;
    //            resolvedTargetContainer = baseSymbol.resolvedType.baseType;
    //            goto resolveArgument;
    //        }

    //        // ExprValue.prop
    //        instance = resolvedTarget.getValue(context, targetInstance, this);
    //        if (instance == null) {
    //            return null;
    //        }
    //        resolvedTargetContainer = instance.resolvedType;
    //        fliterProtectedMembers = !ResolveHelper.canAccessProtected(context.currentMemberDefinition, instance);

    //        // DynamicObject.prop
    //        if (resolvedTargetContainer == PredefinedTypes.dynamic) {
    //            return resolveDynamicSymbol(instance);
    //        }

    //    resolveArgument:

    //        // Expr.prop
    //        var argumentIdentifier = argument as Identifier;
    //        if (argumentIdentifier != null) {
    //            var result = context.currentMemberDefinition.bindAllMembers(resolvedTargetContainer, argumentIdentifier.value, 0, fliterProtectedMembers);
    //            if (result == null) {
    //                ResolveHelper.reportBindSymbolError(context.currentMemberDefinition, resolvedTargetContainer, argumentIdentifier.value, 0, argumentIdentifier);
    //                return null;
    //            }

    //            return ResolveHelper.checkOverload(result, argumentIdentifier.value, argument);
    //        }

    //        // Expr.prop<int>
    //        var argumentGenericExpression = argument as GenericTypeExpression;
    //        if (argumentGenericExpression != null) {
    //            var result = context.currentMemberDefinition.bindAllMembers(resolvedTargetContainer, argumentGenericExpression.elementType.value, argumentGenericExpression.genericArguments.Count, fliterProtectedMembers);
    //            if (result == null) {
    //                ResolveHelper.reportBindSymbolError(context.currentMemberDefinition, resolvedTargetContainer, argumentGenericExpression.elementType.value, argumentGenericExpression.genericArguments.Count, argument);
    //                return null;
    //            }

    //            result = ResolveHelper.checkOverload(result, argumentGenericExpression.elementType.value, argumentGenericExpression);
    //            if (result == null) {
    //                return null;
    //            }

    //            return ResolveHelper.makeGenericSymbol(result, argumentGenericExpression.genericArguments, context, symbolUsage, argumentGenericExpression);
    //        }

    //        throw new Unreachable();

    //    }

    //    private ISymbol resolveDynamicSymbol(Expression targetValue) {
    //        Compiler.echo(targetValue.ToString() + "  symbol   ");
    //        var result = new ResolvedDynamicMemberCallExpression();



    //        return null;
    //    }

    //    /// <summary>
    //    /// 将当前表达式作为值解析。
    //    /// </summary>
    //    /// <param name="context">用于存储所有解析信息的上下文对象。</param>
    //    /// <returns>返回解析后的新表达式，它的所有子表达式都已经被解析。如果解析出现错误则返回 null。</returns>
    //    public override Expression resolveAsValue(ResolveContext context) {
    //        return base.resolveAsSymbolAndGetValue(context);
    //    }

    //}

}
